
#include "main.h"


#define gpio_PWM_CH1_CLK		RCC_AHB1Periph_GPIOA
#define gpio_PWM_CH1_PORT		GPIOA
#define gpio_PWM_CH1_PIN		GPIO_Pin_6
#define gpio_PWM_CH1_AFTYPE		eAFCLK_APB1
#define gpio_PWM_CH1_AFCLK		RCC_APB1Periph_TIM3
#define gpio_PWM_CH1_AFPINSRC	GPIO_PinSource6
#define gpio_PWM_CH1_AF			GPIO_AF_TIM3

#define gpio_PWM_CH2_CLK		RCC_AHB1Periph_GPIOA
#define gpio_PWM_CH2_PORT		GPIOA
#define gpio_PWM_CH2_PIN		GPIO_Pin_7
#define gpio_PWM_CH2_AFTYPE		eAFCLK_APB1
#define gpio_PWM_CH2_AFCLK		RCC_APB1Periph_TIM3
#define gpio_PWM_CH2_AFPINSRC	GPIO_PinSource7
#define gpio_PWM_CH2_AF			GPIO_AF_TIM3

#define gpio_PWM_CH3_CLK		RCC_AHB1Periph_GPIOB
#define gpio_PWM_CH3_PORT		GPIOB
#define gpio_PWM_CH3_PIN		GPIO_Pin_0
#define gpio_PWM_CH3_AFTYPE		eAFCLK_APB1
#define gpio_PWM_CH3_AFCLK		RCC_APB1Periph_TIM3
#define gpio_PWM_CH3_AFPINSRC	GPIO_PinSource0
#define gpio_PWM_CH3_AF			GPIO_AF_TIM3

#define gpio_PWM_CH4_CLK		RCC_AHB1Periph_GPIOB
#define gpio_PWM_CH4_PORT		GPIOB
#define gpio_PWM_CH4_PIN		GPIO_Pin_1
#define gpio_PWM_CH4_AFTYPE		eAFCLK_APB1
#define gpio_PWM_CH4_AFCLK		RCC_APB1Periph_TIM3
#define gpio_PWM_CH4_AFPINSRC	GPIO_PinSource1
#define gpio_PWM_CH4_AF			GPIO_AF_TIM3


#define	tim_MAX_PERIOD			665


TIM_OCInitTypeDef _ocInitStructure =
{
	TIM_OCMode_PWM1,			// TIM_OCMode
	TIM_OutputState_Enable,		// TIM_OutputState
	0,							// //TIM_OutputNState
	0,							// TIM_Pulse
	TIM_OCPolarity_High,		// TIM_OCPolarity
	0,							// //TIM_OCNPolarity
	0,							// //TIM_OCIdleState
	0							// //TIM_OCNIdleState
};


void Pwm_Init(u8 *pDefPwms)
{
	GPIO_INIT gis[] =
	{
		{gpio_PWM_CH1_CLK, {gpio_PWM_CH1_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_PWM_CH1_PORT,
			gpio_PWM_CH1_AFTYPE, gpio_PWM_CH1_AFCLK, gpio_PWM_CH1_AFPINSRC, gpio_PWM_CH1_AF},
		{gpio_PWM_CH2_CLK, {gpio_PWM_CH2_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_PWM_CH2_PORT,
			gpio_PWM_CH2_AFTYPE, gpio_PWM_CH2_AFCLK, gpio_PWM_CH2_AFPINSRC, gpio_PWM_CH2_AF},
		{gpio_PWM_CH3_CLK, {gpio_PWM_CH3_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_PWM_CH3_PORT,
			gpio_PWM_CH3_AFTYPE, gpio_PWM_CH3_AFCLK, gpio_PWM_CH3_AFPINSRC, gpio_PWM_CH3_AF},
		{gpio_PWM_CH4_CLK, {gpio_PWM_CH4_PIN, GPIO_Mode_AF, GPIO_Speed_100MHz, GPIO_OType_PP, GPIO_PuPd_UP}, gpio_PWM_CH4_PORT,
			gpio_PWM_CH4_AFTYPE, gpio_PWM_CH4_AFCLK, gpio_PWM_CH4_AFPINSRC, gpio_PWM_CH4_AF},
	};
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;

	Util_GpioInit(gis, _countof(gis));

	/* -----------------------------------------------------------------------
	TIM3 Configuration: generate 4 PWM signals with 4 different duty cycles.

	In this example TIM3 input clock (TIM3CLK) is set to 2 * APB1 clock (PCLK1),
	since APB1 prescaler is different from 1.
	  TIM3CLK = 2 * PCLK1
	  PCLK1 = HCLK / 4
	  => TIM3CLK = HCLK / 2 = SystemCoreClock / 2

	To get TIM3 counter clock at 20 MHz, the prescaler is computed as follows:
	   Prescaler = (TIM3CLK / TIM3 counter clock) - 1
	   Prescaler = ((SystemCoreClock / 2) /20 MHz) - 1

	To get TIM3 output clock at 30 KHz, the period (ARR)) is computed as follows:
	   ARR = (TIM3 counter clock / TIM3 output clock) - 1
	       = 665
	----------------------------------------------------------------------- */
	/* Time base configuration */
	TIM_TimeBaseStructure.TIM_Period = tim_MAX_PERIOD;
	TIM_TimeBaseStructure.TIM_Prescaler = (u16)((SystemCoreClock / 2) / 20000000) - 1;	// Compute the prescaler value
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

	/* PWM1 Mode configuration: Channel1 */
	TIM_OC1Init(TIM3, &_ocInitStructure);
	TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
	/* PWM1 Mode configuration: Channel2 */
	TIM_OC2Init(TIM3, &_ocInitStructure);
	TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
	/* PWM1 Mode configuration: Channel3 */
	TIM_OC3Init(TIM3, &_ocInitStructure);
	TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
	/* PWM1 Mode configuration: Channel4 */
	TIM_OC4Init(TIM3, &_ocInitStructure);
	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

	TIM_ARRPreloadConfig(TIM3, ENABLE);
	TIM_Cmd(TIM3, ENABLE);

	for (u32 i=0; i<_countof(gis); i++)
		Pwm_Set((PWM_TYPE)i, pDefPwms[i]);
}

u8 Pwm_Set(u8 pwm, u8 percent)
{
	if (ePWM_MAX > (PWM_TYPE)pwm)
	{
		percent = min(max(percent, DATA_PWM_MIN), DATA_PWM_MAX);

		_ocInitStructure.TIM_Pulse = (u32)((float)(percent * tim_MAX_PERIOD) / 100. + 0.5);
		switch ((PWM_TYPE)pwm)
		{
		case ePWM_CH1:
			TIM_OC1Init(TIM3, &_ocInitStructure);
			TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
			break;
		case ePWM_CH2:
			TIM_OC2Init(TIM3, &_ocInitStructure);
			TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);
			break;
		case ePWM_CH3:
			TIM_OC3Init(TIM3, &_ocInitStructure);
			TIM_OC3PreloadConfig(TIM3, TIM_OCPreload_Enable);
			break;
		case ePWM_CH4:
			TIM_OC4Init(TIM3, &_ocInitStructure);
			TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);
			break;
		}

		return percent;
	}

	return 0xFF;
}

